package com.mldong.modules.sys.service.impl;

import cn.dev33.satoken.stp.StpInterface;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.mldong.base.CommonPage;
import com.mldong.base.CommonResult;
import com.mldong.holder.LoginUserHolder;
import com.mldong.modules.sys.dto.RoleMenuParam;
import com.mldong.modules.sys.dto.UserPageParam;
import com.mldong.modules.sys.dto.UserRoleParam;
import com.mldong.modules.sys.entity.RoleMenu;
import com.mldong.modules.sys.entity.UserRole;
import com.mldong.modules.sys.service.RbacService;
import com.mldong.modules.sys.service.RoleMenuService;
import com.mldong.modules.sys.service.UserRoleService;
import com.mldong.modules.sys.service.UserService;
import com.mldong.modules.sys.vo.LoginVO;
import com.mldong.modules.sys.vo.UserVO;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class RbacServiceImpl implements RbacService, StpInterface {
    private final RoleMenuService roleMenuService;
    private final UserRoleService userRoleService;
    private final UserService userService;
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveRoleMenu(List<RoleMenuParam> param) {
        if(CollectionUtil.isEmpty(param))return;
        List<RoleMenu> roleMenuList = BeanUtil.copyToList(param,RoleMenu.class);
        List<String> menuIds = this.getMenuIdsByUserId(LoginUserHolder.getUserId());
        boolean isSuperAdmin = LoginUserHolder.get().isSuperAdmin();
        // 用户只能保存自己拥有菜单权限
        roleMenuList = roleMenuList.stream().filter(item->{
            if(isSuperAdmin){
                return true;
            }
            return menuIds.contains(item.getMenuId().toString());
        }).collect(Collectors.toList());
        // 删除旧的关系
        LambdaQueryWrapper<RoleMenu> delLambdaQueryWrapper = Wrappers.lambdaQuery();
        delLambdaQueryWrapper.eq(RoleMenu::getRoleId,param.get(0).getRoleId());
        roleMenuService.remove(delLambdaQueryWrapper);
        // 重新保存新的关系
        roleMenuService.saveBatch(roleMenuList);
    }

    @Override
    public List<String> roleMenuIds(Long roleId) {
        LambdaQueryWrapper<RoleMenu> lambdaQueryWrapper = Wrappers.lambdaQuery();
        lambdaQueryWrapper.eq(RoleMenu::getRoleId,roleId);
        List<RoleMenu> roleMenuList = roleMenuService.list(lambdaQueryWrapper);
        List<String> menuIds = roleMenuList.stream().map(item->{
            return item.getMenuId().toString();
        }).collect(Collectors.toList());
        return menuIds;
    }

    @Override
    public List<String> getMenuIdsByUserId(Long userId) {
        // 获取某个用户的角色ID
        List<Long> roleIds = userRoleService.list(
                Wrappers.lambdaQuery(UserRole.class)
                .eq(UserRole::getUserId,userId)
        ).stream().map(item->item.getRoleId()).collect(Collectors.toList());
        if(CollectionUtil.isEmpty(roleIds)) return new ArrayList<>();
        // 获取角色菜单关系
        LambdaQueryWrapper<RoleMenu> lambdaQueryWrapper = Wrappers.lambdaQuery();
        lambdaQueryWrapper.in(RoleMenu::getRoleId,roleIds);
        List<RoleMenu> roleMenuList = roleMenuService.list(lambdaQueryWrapper);
        // 获取菜单
        List<String> menuIds = roleMenuList.stream().map(item->{
            return item.getMenuId().toString();
        }).collect(Collectors.toList());
        return menuIds;
    }

    @Override
    public CommonPage<UserVO> userListByRoleId(UserPageParam param) {
        return userService.page(param);
    }

    @Override
    public CommonPage<UserVO> userListExcludeRoleId(UserPageParam param) {
        param.setExcludeRoleId(param.getRoleId());
        param.setRoleId(null);
        return userService.page(param);
    }

    @Override
    public void saveUserRole(List<UserRoleParam> params) {
        if(CollectionUtil.isEmpty(params))return;
        List<UserRole> userRoleList = BeanUtil.copyToList(params,UserRole.class);
        List<UserRole> insertList = userRoleList.stream().filter(item->{
            LambdaQueryWrapper<UserRole> lambdaQueryWrapper = Wrappers.lambdaQuery();
            lambdaQueryWrapper.eq(UserRole::getUserId,item.getUserId())
                    .eq(UserRole::getRoleId,item.getRoleId());
            return userRoleService.count(lambdaQueryWrapper)==0;
        }).collect(Collectors.toList());
        if(CollectionUtil.isNotEmpty(insertList)) {
            userRoleService.saveBatch(userRoleList);
        }
    }

    @Override
    public void removeUserRole(List<UserRoleParam> params) {
        if(CollectionUtil.isEmpty(params))return;
        List<UserRole> userRoleList = BeanUtil.copyToList(params,UserRole.class);
        userRoleList.forEach(userRole->{
            LambdaQueryWrapper<UserRole> delLambdaQueryWrapper = Wrappers.lambdaQuery();
            delLambdaQueryWrapper.eq(UserRole::getUserId,userRole.getUserId())
                    .eq(UserRole::getRoleId,userRole.getRoleId());
            userRoleService.remove(delLambdaQueryWrapper);
        });
    }

    @Override
    public List<String> getPermissionList(Object loginId, String loginTyp) {
        LoginVO vo = BeanUtil.toBean(StpUtil.getExtra(LoginVO.class.getSimpleName()),LoginVO.class);
        //return CollectionUtil.newArrayList("sys:user:page");
        return vo.getPerms();
    }

    @Override
    public List<String> getRoleList(Object loginId, String loginTyp) {
        return new ArrayList<>();
    }
}
